/*
 *                    BioJava development code
 *
 * This code may be freely distributed and modified under the
 * terms of the GNU Lesser General Public Licence.  This should
 * be distributed with the code.  If you do not have a copy,
 * see:
 *
 *      http://www.gnu.org/copyleft/lesser.html
 *
 * Copyright for this code is held jointly by the individual
 * authors.  These should be listed in @author doc comments.
 *
 * For more information on the BioJava project and its aims,
 * or to join the biojava-l mailing list, visit the home page
 * at:
 *
 *      http://www.biojava.org/
 *
 * Created on 15.04.2004
 * @author Andreas Prlic
 *
 */
package dasregistry ;

import java.util.*;
import java.io.Serializable;
import java.sql.*                             ;
import javax.sql.DataSource                   ;

import org.biojava.dasobert.dasregistry.DasSource;
import org.biojava.services.das.registry.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import org.biojava.services.das.dao.*;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;



public class coordBean implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;


	String[] categories ;
	String   organism;
	String   name;
	String newname;
	String message;
	String prefix;
	String keyword;
	int ncbiId;
	//protected RegistryPooledDataSource dataSourcePool;
	//   
	//Map configuration ;

	static final int DEFAULTTAXID = -1;
	//DasSourceManager dao;    

//	DasRegistrySql registry;
//	UserManager manager;
//	DasUserDAO userDAO;
 private DasRegistrySql getRegistry(){
		BeanFactory ctx=(new ClassPathXmlApplicationContext("SpringDAO.xml"));
		return (DasRegistrySql)ctx.getBean("registryBean");
//		dataSource=registry.getDataSource();
//		manager=registry.getUserManager();
//		userDAO=registry.getDasUserDao();
 }
 private DataSource getDataSource(){
	return  this.getRegistry().getDataSource();
//		dataSource=registry.getDataSource();
//		manager=registry.getUserManager();
//		userDAO=registry.getDasUserDao();
 }
 
 private DasUserDAO getDasUserDAO()
 {
return  this.getRegistry().getDasUserDao();
 }
 
 private UserManager getUserManager(){
	 return  this.getRegistry().getUserManager();
 }

	//private DataSource dataSource;
	
	public coordBean() {
		newname = "";
		name = "";
		organism = "";
		message = "" ;
		prefix = "";
		ncbiId = DEFAULTTAXID;
		categories = new String[1];
		categories[0] = "undefined";
		keyword = "";

		
//		BeanFactory ctx=(new ClassPathXmlApplicationContext("SpringDAO.xml"));
//		registry=(DasRegistrySql)ctx.getBean("registryBean");
//		dataSource=registry.getDataSource();
//		manager=registry.getUserManager();
//		userDAO=registry.getDasUserDao();



	}

	public void setKeyword(String kw){
		keyword = kw;
	}

	public String getKeyword(){
		return keyword;
	}

	public void setCategories(String[] cat) {
		categories = cat;
	}

	public String[] getCategories() {
		return categories ;
	}

	public void setOrganism (String org) {

		organism = org;
	}

	public String getOrganism() {
		return organism;
	}

	public void setName(String nam) {
		name = nam;
	}
	public String getName() {
		return name;
	}

	public void setNewName(String name) {
		newname = name;
	}

	public String getNewName() {
		return newname ;
	}

	public void setPrefix(String p){ prefix = p;}
	public String getPrefix(){ return prefix;}

	public void setNCBITaxId(int ncbiid){ ncbiId = ncbiid;}
	public int getNCBITaxId(){ return ncbiId;}

	
	
	public ProjectBean getProject(int project_id){
		UserDAO dao = new UserDAO();
		Connection conn = null;
		ProjectBean project = null;

		try {
			conn = this.getDataSource().getConnection() ;

			project = dao.getProjectForId(this.getUserManager(), conn, project_id);

		} catch ( SQLException e) {

			e.printStackTrace();
		} finally {
			if ( conn != null ) {
				try {
					conn.close();
				} catch ( SQLException ex) {
					ex.printStackTrace();
				}
			}
		}

		return project;

	}
	
	
	
	public RegistryUser[] getOwnersForSource(DasSource ds){
		
		
		int auto_id = this.getRegistry().getAutoID4DasSource(ds);
		
		return this.getUserManager().getOwners(auto_id);
		
	}

	
	/** remove server
	 * an int is returned, wich provides the status of the request:
	 *  1: successfully removed
	 *  2:  incorrect key ;
	 *  0: some other error occured;
	 * @param serverurl 
	 * @param user the owner of the DAS source 
	 * @return the status of the request 
	 */
	public int removeService(String serverurl, RegistryUser user){
		//check if this user owns this url using the userDAO
		//if so ask the registry to remove it
		return this.getRegistry().removeService(serverurl, user);

	}
	

	public boolean userOwnsSource(RegistryUser user, DasSource ds){
		
					
		int auto_id = this.getRegistry().getAutoID4DasSource(ds);
		if ( this.getUserManager().isOwner(user, auto_id) )
			return true;
				
		return false;
	}
	
	public boolean userOwnsASource(RegistryUser user, DasSource[] sources){

		for (int i =0; i< sources.length;i++){
			DasSource ds = sources[i];
			int auto_id = this.getRegistry().getAutoID4DasSource(ds);
			if ( this.getUserManager().isOwner(user, auto_id) )
				return true;
		}
		
		return false;
		
	}
	
	
	
	public ProjectBean[] getAdminProjectsForUser(RegistryUser user){
		
		
		Connection conn = null;
		ProjectBean[] projects = new ProjectBean[0];

		try {
			conn = this.getDataSource().getConnection() ;

			projects = this.getDasUserDAO().getAdminProjectsForUser(conn, user);

		} catch ( SQLException e) {

			e.printStackTrace();
		} finally {
			if ( conn != null ) {
				try {
					conn.close();
				} catch ( SQLException ex) {
					ex.printStackTrace();
				}
			}
		}

		return projects;


		
	}
	
	public DasSource[] getDasSourcesForProject(ProjectBean project){
		DasSource[] sources = new DasSource[0];
		sources = this.getRegistry().getDasSourcesForProject(project.getProjectID());		
		
		return sources;
		
	}
	
	public int getNrDasSourcesForProject(ProjectBean project){

		
		
		Connection conn = null;
		int nr = 0;

		try {
			conn = this.getDataSource().getConnection() ;

			nr = this.getDasUserDAO().getNrDasSourcesForProject(conn,project);

		} catch ( SQLException e) {

			e.printStackTrace();
		} finally {
			if ( conn != null ) {
				try {
					conn.close();
				} catch ( SQLException ex) {
					ex.printStackTrace();
				}
			}
		}

		return nr;


	}

	
	
	public ProjectBean[] getAllProjects(){

		
		
		Connection conn = null;
		ProjectBean[] projects = new ProjectBean[0];

		try {
			conn = this.getDataSource().getConnection() ;

			projects = this.getDasUserDAO().getAllProjects(conn);

		} catch ( SQLException e) {

			e.printStackTrace();
		} finally {
			if ( conn != null ) {
				try {
					conn.close();
				} catch ( SQLException ex) {
					ex.printStackTrace();
				}
			}
		}

		return projects;


	}

	public ProjectBean[] getProjectsForUser(RegistryUser user ){
		
		ProjectBean[] userProjects = getAdminProjectsForUser(user);
		
		List tmp = Arrays.asList(userProjects);
		List projects = new ArrayList();
		projects.addAll(tmp);
		
		
		ProjectBean[] allProjects =  getAllProjects();
		for (int i = 0; i < allProjects.length; i++) {
			ProjectBean project = allProjects[i];
			
			boolean isKnown = false;
			Iterator iter = projects.iterator();
			while (iter.hasNext()){
				ProjectBean tmpp = (ProjectBean)iter.next();
				if ( tmpp.equals(project)) {
					isKnown = true;
					break;
				}
			}
			if ( isKnown)
				continue;
			
			
			DasSource[] projectSources = getDasSourcesForProject(project);
			
			boolean userOwnsOneSource = userOwnsASource(user,projectSources);
			if ( userOwnsOneSource){								
					projects.add(project);
			}
		}
		return (ProjectBean[]) projects.toArray(new ProjectBean[projects.size()]);
	}


	public ProjectBean getProjectBeanForURL(String das_source_url){

		Connection conn = null;
		ProjectBean project = null;

		

		try {
			conn = this.getDataSource().getConnection() ;
			 
			project = this.getDasUserDAO().getProjectForURL(conn, das_source_url);

		} catch ( SQLException e) {

			e.printStackTrace();
		} finally {
			if ( conn != null ) {
				try {
					conn.close();
				} catch ( SQLException ex) {
					ex.printStackTrace();
				}
			}
		}

		return project;


	}

    /** Note that this method will create any missing species'. This is used
     *  when mirroring/caching coordinate systems
     *
     * @param conn
     * @throws java.sql.SQLException
     */
	public void createCoordinateSystem(Connection conn) throws SQLException {
		int coord_auto = -1;
		BeanFactory ctx=(new ClassPathXmlApplicationContext("SpringDAO.xml"));
		DasSourceManager dao=(DasSourceManager) ctx.getBean("dasSourceManager");

		if (
				( newname != null ) &&
				( ! newname.equals("") )
		)
		{
			
			String[] spl = newname.split("_");
			String version = null;
			if (spl.length == 2){
				newname = spl[0];
				version = spl[1];
			}
			
			coord_auto = dao.getCoordAuto(conn,newname,version) ;
			if ( coord_auto == -1 ) {
				coord_auto = dao.createNewCsName(conn,newname,version);
			}		
		} else {
			
			String[] spl = name.split("_");
			
			String version = null;
			if (spl.length == 2){
				name = spl[0];
				version = spl[1];
			}
			
			coord_auto = dao.getCoordAuto(conn,name,version);
            if ( coord_auto == -1 ) {
                throw new SQLException("Unknown coordinate system name: " + name + " " + version);
            }
		}

        // If the organism doesn't exist, create it
		testCreateNCBITaxId(conn,organism);
		int ncbi_tax_id = ncbiId;
		if ( ncbiId == -1){
			ncbi_tax_id = dao.getNCBITaxId(conn,organism);
		}

		for ( int i=0 ; i < categories.length; i++ ){
			String category = categories[i];
			int category_auto = dao.getCategoryAuto(conn,category);
            if ( coord_auto == -1 ) {
                throw new SQLException("Unknown coordinate system category: " + category);
            }
			String thisprefix = prefix;
			if ( prefix.equals(""))
				thisprefix = null;
			dao.createCoordSys(conn,coord_auto,category_auto,ncbi_tax_id,thisprefix);
		}
		dao.pingLastModified(conn);
	}

	/** put this coordinate System into the database 

	 * return 1 if creation o.k
	 * returns 0 is problem occured
	 * @return flags
	 */
	public int create(){
		Connection conn = null;

		try {




			message = "" ;
			conn = this.getDataSource().getConnection() ;
			createCoordinateSystem(conn);

			conn.close();
			return 1;
		} catch ( SQLException e) {
			message = e.getMessage();
			e.printStackTrace();
			if ( conn != null ) {
				try {
					conn.close();
				} catch ( SQLException ex) {
					ex.printStackTrace();
				}
			}	    
		}
		return 0;
	}


	private void testCreateNCBITaxId(Connection conn, String organism) throws SQLException{
		BeanFactory ctx=(new ClassPathXmlApplicationContext("SpringDAO.xml"));
		DasSourceManager dao=(DasSourceManager) ctx.getBean("dasSourceManager");
		try {
			dao.getNCBITaxId(conn,organism);
		}
		catch (SQLException e) {
			//System.out.println("did not find organism " + organism );
			// 	try to create it ...
			String org = getOrganism();
			//System.out.println("oorg:" +org);
			if ( org != null ) {
				int txid= getNCBITaxId();
				//System.out.println( "trying to creeate with taxid "+txid);
				if ( txid != DEFAULTTAXID) {
					dao.createOrganism(conn,org,organism,txid);
				}
			}
		}
	}


	public String getMessage(){ return message ; }

	public String[] getNames() {
		List lst = new ArrayList();
		Connection conn = null ;


		try {
			conn = this.getDataSource().getConnection() ;

			String sql = "SELECT coordinateSystem , version FROM cs_names ";
			PreparedStatement ps = conn.prepareStatement(sql);

			ResultSet rs = ps.executeQuery();
			while ( rs.next() ) {
				String cs = rs.getString(1);
				String version = rs.getString(2);
				String name = cs;
				if ( (version != null) && (!  version.equals(""))){
					name += DasRegistrySql.PREFIXSPLIT + version;
				}

				lst.add(name);
			}            
		} catch ( SQLException e) {
			message = e.getMessage();
			e.printStackTrace();
		} finally {
			if ( conn != null ) {
				try {
					conn.close();
				} catch ( SQLException ex) {
					ex.printStackTrace();
				}
			}
		}
		return (String[]) lst.toArray(new String[lst.size()]);
	}    
}
